/**
 * 
 */
package com.wistech.search.solr.dict.file;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wltea.analyzer.cfg.Configuration;
import org.wltea.analyzer.dic.Dictionary;

import com.wistech.search.solr.dict.AbstractDictDetector;
import com.wistech.search.solr.dict.Callback;
import com.wistech.search.solr.dict.Dict;
import com.wistech.search.solr.dict.DictDetector;
import com.wistech.search.solr.dict.DictReader;
import com.wistech.search.solr.dict.file.sougou.ScelDictReader;
import com.wistech.search.solr.dict.file.txt.TxtDictReader;

/**
 * @author Liuye
 * 
 */
public class FileDictDetector extends AbstractDictDetector implements
		DictDetector {
	private static final Logger log = LoggerFactory
			.getLogger(FileDictDetector.class);
	/**
	 * 词库目录
	 */
	private String dictDir;

	/** 记录 dict文件的最后修改时间 */
	final Map<File, Long> dictLastModified = new HashMap<File, Long>();

	public FileDictDetector(String dictDir) {
		this(dictDir, RefreshMode.DAY);
	}

	public FileDictDetector(String dictDir, RefreshMode refreshMode) {
		this(dictDir, refreshMode, DEFAULT_TERM_MIN_LENGTH);
	}

	public FileDictDetector(String dictDir, RefreshMode refreshMode,
			int minLength) {
		this(dictDir, refreshMode, minLength, DEFAULT_TERM_MAX_LENGTH);
	}

	public FileDictDetector(String dictDir, RefreshMode refreshMode,
			int minLength, int maxLength) {
		setDictDir(dictDir);
		setRefreshMode(refreshMode);
		setMinLength(minLength);
		setMaxLength(maxLength);
	}

	public void setDictDir(String dictDir) {
		this.dictDir = dictDir;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.wistech.solr.dict.file.AbstractDictDetector#stop()
	 */
	@Override
	public void stop() {
		super.stop();
		this.dictLastModified.clear();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.wistech.solr.dict.file.DictDetector#loadDict()
	 */
	@Override
	public void loadDict() {
		log.info("开始加载目录：" + dictDir + " 下的词库文件 ...");
		final Set<String> words = new HashSet<String>(1024);
		// 加载词库目录词库
		DictLoader loader = new DictLoader();
		loader.load(dictDir, new Callback<Dict>() {
			@Override
			public void doCallback(Dict dict) {
				for (String term : dict.getTerms()) {
					if (term != null) {
						term = term.trim();
						if ((term.length() >= minLength && term.length() <= maxLength)
								&& !words.contains(term)) {
							words.add(term);
						}
					}
				}
			}
		});

		// 更新Ik的扩展词库
		Dictionary.initial(Configuration.getInstance());
		Dictionary.getSingleton().addWords(words);
	}

	protected class DictLoader {
		private Callback<Dict> callBack;

		public void load(String path, Callback<Dict> callBack) {
			this.callBack = callBack;
			File dir = new File(path);
			// 确定该路径指向一个目录
			if (dir.exists() && dir.isDirectory()) {
				readFolder(dir);
			}
		}

		private void readFolder(File dir) {
			// 列出所有结尾为txt的文件
			File[] files = dir.listFiles(new FilenameFilter() {
				@Override
				public boolean accept(File dir, String name) {
					File file = new File(dir, name);
					return file.isDirectory()
							|| (file.isFile()
									&& (name.endsWith(".scel") || name
											.endsWith(".txt")) && isModified(file));
				}

				private boolean isModified(File file) {
					long modifiedTime = file.lastModified();
					if (dictLastModified.containsKey(file)) {
						long lastModifiedTime = dictLastModified.get(file);
						return modifiedTime > lastModifiedTime;
					}
					return true;
				}
			});
			for (File file : files) {
				if (file.isDirectory()) {
					readFolder(file);
				}
				if (file.isFile()) {
					read(file);
				}
			}

		}

		private void read(File file) {
			DictReader reader = null;
			try {
				log.info("加载文件： " + file.getCanonicalPath() + "中的词库。");
				reader = createDictReader(file);
				dictLastModified.put(file, file.lastModified());
				callBack.doCallback(reader.read());
			} catch (Exception e) {
				try {
					log.error("读取词库文件异常。" + file.getCanonicalPath(), e);
				} catch (IOException e1) {
				}

			} finally {
				if (reader != null) {
					try {
						reader.close();
					} catch (IOException e) {
					}
				}
			}
		}

		private DictReader createDictReader(File file) throws IOException {
			String filename = file.getName();
			if (filename.endsWith(".scel")) {
				return new ScelDictReader(file);
			}
			if (filename.endsWith(".txt")) {
				return new TxtDictReader(file);
			}
			throw new RuntimeException("暂不支持此种格式的词库:" + filename);
		}
	}
}
